﻿#include "UdpClient.h"
#include "ui_UdpClient.h"

UdpClient::UdpClient(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::UdpClient)
{
    ui->setupUi(this);

    initUi();

    labSocketState = new QLabel("Socket状态:");

    labSocketState->setMinimumWidth(150);

    ui->statusbar->addWidget(labSocketState);

    QString localIp = getLocalIp();
    this->setWindowTitle(this->windowTitle() + QStringLiteral("---本机Ip:") + localIp);
    ui->comboTargetIp->addItem(localIp);

    udpSocket = new QUdpSocket(this);

    connect(udpSocket, &QUdpSocket::stateChanged, this, &UdpClient::onSocketStateChanged);
    connect(udpSocket, &QUdpSocket::readyRead, this, &UdpClient::onSocketReadyRead);
}

UdpClient::~UdpClient()
{
    delete ui;
}

void UdpClient::initUi()
{
    QToolBar* bar = new QToolBar(this);

    this->addToolBar(Qt::ToolBarArea::TopToolBarArea, bar);

    actBindPort = new QAction(QStringLiteral("绑定端口"));
    actNotBindPort = new QAction(QStringLiteral("解除绑定"));
    actClearText = new QAction(QStringLiteral("清空文本框"));
    actQuit = new QAction(QStringLiteral("退出"));
    bar->addAction(actBindPort);
    bar->addAction(actNotBindPort);
    bar->addAction(actClearText);
    bar->addAction(actQuit);

    connect(actBindPort, &QAction::triggered, this, &UdpClient::onActBindPort);
    connect(actNotBindPort, &QAction::triggered, this, &UdpClient::onActNotBindPort);
    connect(actClearText, &QAction::triggered, this, &UdpClient::onActClearText);
    connect(actQuit, &QAction::triggered, this, &UdpClient::onActQuit);
}

QString UdpClient::getLocalIp()
{
    // 获取本机IPv4地址
    QString hostName = QHostInfo::localHostName();
    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    QString localIp = "";
    QList<QHostAddress> addrList = hostInfo.addresses();
    if(!addrList.isEmpty())
        for (int i = 0; i < addrList.count(); i++) {
            QHostAddress aHost = addrList.at(i);
            if(QAbstractSocket::IPv4Protocol == aHost.protocol())
            {
                localIp = aHost.toString();
                break;
            }
        }
    return localIp;
}

void UdpClient::onSocketStateChanged(QAbstractSocket::SocketState socketState)
{
    // socket状态变化
    switch(socketState)
    {
    case QAbstractSocket::UnconnectedState  :
        labSocketState->setText(QStringLiteral("socket状态:UnconnectedState"));
        break;
    case QAbstractSocket::HostLookupState   :
        labSocketState->setText(QStringLiteral("socket状态:HostLookupState"));
        break;
    case QAbstractSocket::ConnectingState   :
        labSocketState->setText(QStringLiteral("socket状态:ConnectingState"));
        break;
    case QAbstractSocket::ConnectedState    :
        labSocketState->setText(QStringLiteral("socket状态:ConnectedState"));
        break;
    case QAbstractSocket::BoundState        :
        labSocketState->setText(QStringLiteral("socket状态:BoundState"));
        break;
    case QAbstractSocket::ListeningState    :
        labSocketState->setText(QStringLiteral("socket状态:ListeningState"));
        break;
    case QAbstractSocket::ClosingState      :
        labSocketState->setText(QStringLiteral("socket状态:ClosingState"));
        break;
    }
}

void UdpClient::onSocketReadyRead()
{
    // 读取收到的数据报
    while(udpSocket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        QHostAddress peerAddr;
        quint16 peerPort;
        udpSocket->readDatagram(datagram.data(), datagram.size(), &peerAddr, &peerPort);

        QString msg = datagram.data();
        QString peer = "[From " + peerAddr.toString() + ":" + QString::number(peerPort) + "] ";
        ui->plainTextEdit->appendPlainText(peer + msg);
    }
}

void UdpClient::onActBindPort()
{
    // 绑定端口

    // 本机UDP端口
    quint16 port = ui->bindPort->value();
    //绑定端口成功
    if(udpSocket->bind(port))
    {
        ui->plainTextEdit->appendPlainText(QStringLiteral("**已成功绑定"));
        ui->plainTextEdit->appendPlainText(QStringLiteral("**绑定端口：") + QString::number(udpSocket->localPort()));
        actBindPort->setEnabled(false);
        actNotBindPort->setEnabled(true);
    }
    else
    {
        ui->plainTextEdit->appendPlainText(QStringLiteral("**绑定失败"));
    }
}

void UdpClient::onActNotBindPort()
{
    // 解除绑定
    udpSocket->abort();
    actBindPort->setEnabled(true);
    actNotBindPort->setEnabled(false);
    ui->plainTextEdit->appendPlainText(QStringLiteral("**已解除绑定"));
}

void UdpClient::onActClearText()
{
    ui->plainTextEdit->clear();
}

void UdpClient::onActQuit()
{
    close();
}


void UdpClient::on_btnSend_clicked()
{
    // 目标Ip
    QString targetIp = ui->comboTargetIp->currentText();
    // 目标端口
    quint16 targetPort = ui->targetPort->value();

    // 发送的消息内容
    QString msg = ui->edtSend->text();
    QByteArray msgStr = msg.toUtf8();

    // 发送数据
    udpSocket->writeDatagram(msgStr, QHostAddress(targetIp), targetPort);

    ui->plainTextEdit->appendPlainText("[out]" + msg);
    ui->edtSend->clear();
    ui->edtSend->setFocus();
}

void UdpClient::on_btnMultiCastSend_clicked()
{
    // 目标端口
    quint16 targetPort = ui->targetPort->value();

    QString msg = ui->edtSend->text();
    QByteArray msgStr = msg.toUtf8();

    udpSocket->writeDatagram(msgStr, QHostAddress::Broadcast, targetPort);

    ui->plainTextEdit->appendPlainText("[out]" + msg);
    ui->edtSend->clear();
    ui->edtSend->setFocus();
}
